package com.ruoyi.system.service.impl;

import java.util.*;
import java.util.stream.Collectors;

import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.domain.enums.SysConstant;
import com.ruoyi.system.domain.time.*;
import com.ruoyi.system.domain.vo.DateUtil;
import com.ruoyi.system.mapper.ClaTimeAttendMapper;
import com.ruoyi.system.mapper.ScStudentCourseMapper;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import com.ruoyi.system.mapper.ScClaTimeMapper;
import com.ruoyi.system.service.IScClaTimeService;

/**
 * 排课信息Service业务层处理
 * 
 * @author ruoyi
 * @date 2024-01-10
 */
@Service
public class ScClaTimeServiceImpl implements IScClaTimeService 
{
    @Autowired
    private ScClaTimeMapper scClaTimeMapper;

    @Autowired
    private ScStudentCourseMapper scStudentCourseMapper;

    @Autowired
    private ClaTimeAttendMapper claTimeAttendMapper;


    /**
     * 查询排课信息
     * 
     * @param courseTimeId 排课信息主键
     * @return 排课信息
     */
    @Override
    public ScClaTime selectScClaTimeByCourseTimeId(Long courseTimeId)
    {
        return scClaTimeMapper.selectScClaTimeByCourseTimeId(courseTimeId);
    }

    @Override
    public List<ScClaTimeAttend> selectScClaTimeTeacherIdList(ScClaTime scClaTime) {
        return scClaTimeMapper.selectScClaTimeTeacherIdList(scClaTime);
    }
    @Override
    public List<ScClaTimeAttend> selectScClaTimeClaIdList(ScClaTime scClaTime) {
        return scClaTimeMapper.selectScClaTimeClaIdList(scClaTime);
    }

    /**
     * 查询排课信息列表
     * 
     * @param scClaTime 排课信息
     * @return 排课信息
     */
    @Override
    public List<ScClaTime> selectScClaTimeList(ScClaTime scClaTime)
    {
        return scClaTimeMapper.selectScClaTimeList(scClaTime);
    }

    @Override
    public List<ScClaTimeAttend> selectScClaTimeList(ScClaTimeAttend scClaTimeAttend) {
        return scClaTimeMapper.selectScClaTimeAttendList(scClaTimeAttend);
    }

    /**
     * 新增排课信息
     * 
     * @param scClaTime 排课信息
     * @return 结果
     */
    @Override
    public int insertScClaTime(ScClaTime scClaTime)
    {
        scClaTime.setCreateTime(DateUtils.getNowDate());
        return scClaTimeMapper.insertScClaTime(scClaTime);
    }

    /**
     * 修改排课信息
     * 
     * @param scClaTime 排课信息
     * @return 结果
     */
    @Override
    public int updateScClaTime(ScClaTime scClaTime)
    {
        return scClaTimeMapper.updateScClaTime(scClaTime);
    }

    /**
     * 批量删除排课信息
     * 
     * @param courseTimeIds 需要删除的排课信息主键
     * @return 结果
     */
    @Override
    public int deleteScClaTimeByCourseTimeIds(Long[] courseTimeIds)
    {
        return scClaTimeMapper.deleteScClaTimeByCourseTimeIds(courseTimeIds);
    }

    /**
     * 删除排课信息信息
     * 
     * @param courseTimeId 排课信息主键
     * @return 结果
     */
    @Override
    public int deleteScClaTimeByCourseTimeId(Long courseTimeId)
    {
        return scClaTimeMapper.deleteScClaTimeByCourseTimeId(courseTimeId);
    }

    @Override
    public AjaxResult searchListForCalendar(ReqSearchClaTime reqSearchClaTime) {

        String beginDate = reqSearchClaTime.getBeginDate();
        String endDate = reqSearchClaTime.getEndDate();

        if (StringUtils.isAnyEmpty(beginDate, endDate)) {
            return AjaxResult.error("日历选择错误");
        }

        DateTime cycleBegin = DateUtil.yyyMMddDayBegin(beginDate);
        DateTime cycleEnd = DateUtil.yyyMMddDayEnd(endDate);

        if (1 != cycleBegin.getDayOfWeek() || 7 != cycleEnd.getDayOfWeek()) {
            return AjaxResult.error("日历选择错误");
        }
        Long[] longs = null;
        //查找课表为学生时
        if (reqSearchClaTime.getStudentId() != null) {
            longs = scStudentCourseMapper.selectScStudentCourseByStudentId(reqSearchClaTime.getStudentId());
        }
        else if (reqSearchClaTime.getTeacherId() != null){
            longs = scClaTimeMapper.selectScStudentCourseByTeacherId(reqSearchClaTime.getTeacherId());
    }
        reqSearchClaTime.setClaIdList(longs);

        // 日历数据  格式为：时间->星期->课程
        Map<Integer, Map<Integer, List<RespClaTimeCalendar>>> claTimeCalendarMap = new HashMap<>();
        SysConstant.CLA_TIME_MAP.forEach((claTimeKey, claTimeValue) -> {
            Map<Integer, List<RespClaTimeCalendar>> weekDayMap = new HashMap<>();;
            SysConstant.WEEK_DAY_MAP.forEach((weekDayKey, weekDay) -> {
                List<RespClaTimeCalendar> claTimeArrayList = new ArrayList<>();
                weekDayMap.put(weekDayKey, claTimeArrayList);
            });
            claTimeCalendarMap.put(claTimeKey, weekDayMap);
        });

        // 获取排课信息
        List<RespClaTimeCalendar> respClaTimeList = scClaTimeMapper.selectListForCalendar(reqSearchClaTime);

        // 将排课信息 入到 claTimeCalendarMap
        respClaTimeList.forEach(item -> {
            Integer weekDay = item.getWeekDay();
            Integer startHour = item.getStartHour();

            if (claTimeCalendarMap.containsKey(startHour)) {
                claTimeCalendarMap.get(startHour).get(weekDay).add(item);
            } else if (claTimeCalendarMap.containsKey(startHour - 1)) {
                // 每两个小时 一个上课时段，所以-1
                claTimeCalendarMap.get(startHour - 1).get(weekDay).add(item);
            }
        });


        RespBusinessClaTimeCalendar timeCalendar = new RespBusinessClaTimeCalendar();
        // 每行数据
        List<ClaTimeContainer> claTimeContainerList = Lists.newArrayList();
        // 星期排课数量
        Map<Integer, Integer> columnTitleTimeCountMap = new HashMap<>();

        // 每行数据
        claTimeCalendarMap.forEach((claTimeKey, claTimeMap) -> {
            ClaTimeContainer claTimeContainer = new ClaTimeContainer();
            claTimeContainer.setTime(SysConstant.CLA_TIME_MAP.get(claTimeKey));

            Map<Integer, List<ClaTimeCalendarItem>> claTimeWeekDayMap = new HashMap<>();
            claTimeMap.forEach((weekDayKey, list) -> {

                // 排课数量
                if (columnTitleTimeCountMap.containsKey(weekDayKey)) {
                    columnTitleTimeCountMap.put(weekDayKey, columnTitleTimeCountMap.get(weekDayKey) + list.size());
                } else {
                    columnTitleTimeCountMap.put(weekDayKey, list.size());
                }

                List<ClaTimeCalendarItem> timeItemList = list.stream().map(item -> {
                    ClaTimeCalendarItem claTimeItem = new ClaTimeCalendarItem();
                    claTimeItem.transfer(item);
                    return claTimeItem;
                }).collect(Collectors.toList());
                claTimeWeekDayMap.put(weekDayKey, timeItemList);
            });
            claTimeContainer.setClaTimeWeekDayMap(claTimeWeekDayMap);
            claTimeContainerList.add(claTimeContainer);
        });


        Collections.sort(claTimeContainerList, (o1, o2) -> {
            int a = Integer.parseInt(o1.getTime().substring(0, 2));
            int b = Integer.parseInt(o2.getTime().substring(0, 2));
            if (a > b) {
                return 1;
            } else if (a < b) {
                return -1;
            } else {
                return 0;
            }
        });


        timeCalendar.setClaTimeContainer(claTimeContainerList);


        // 标题
        List<ClaTimeColumnTitle> columnTitles = Lists.newArrayList();
        while (cycleBegin.isBefore(cycleEnd)) {
            int dayOfWeek = cycleBegin.getDayOfWeek();

            ClaTimeColumnTitle claTimeColumnTitle = new ClaTimeColumnTitle();
            claTimeColumnTitle.setWeekName(SysConstant.WEEK_DAY_MAP.get(dayOfWeek));
            claTimeColumnTitle.setDay(cycleBegin.toString("MM-dd"));
            claTimeColumnTitle.setCount(columnTitleTimeCountMap.get(dayOfWeek));

            columnTitles.add(claTimeColumnTitle);
            cycleBegin = cycleBegin.plusDays(1);
        }
        timeCalendar.setColumnTitles(columnTitles);

        return AjaxResult.success(timeCalendar);



    }



    @Override
    public AjaxResult searchListForLeave(SearchClaTime searchClaTime) {
        Long[] claId = scStudentCourseMapper.selectScStudentCourseByStudentId(searchClaTime.getStudentId());
        searchClaTime.setClaIds(claId);
        List<ScClaTimeAttend> scClaTimeAttends = scClaTimeMapper.selectLeaveList(searchClaTime);

        return AjaxResult.success(scClaTimeAttends);
    }

    @Override
    @Async("threadPoolTaskExecutor")
    public void searchListForMessageLeave(SysMessage sysMessage) {
        Long[] claId = scStudentCourseMapper.selectScStudentCourseByStudentId(sysMessage.getSendId());
        sysMessage.setClaIds(claId);
        List<ScClaTimeAttend> scClaTimeAttends = scClaTimeMapper.selectsysMessageLeaveList(sysMessage);



        ScStudentCourse scStudentCourse = new ScStudentCourse();
        scStudentCourse.setStudentId(sysMessage.getSendId());


        for (ScClaTimeAttend scClaTimeAttend:
        scClaTimeAttends) {


            scClaTimeMapper.updateCourseTimeId(scClaTimeAttend.getCourseTimeId());

            scStudentCourse.setClaId(scClaTimeAttend.getClaId());
            ScStudentCourse scStudentCourse1 = scStudentCourseMapper.selectScStudentCourseByClaIdANDStudentId(scStudentCourse);

            scClaTimeAttend.setStudentId(sysMessage.getSendId());
            scClaTimeAttend.setStudentCourseId(scStudentCourse1.getStudentCourseId());
            scClaTimeAttend.setCourseId(scStudentCourse1.getCourseId());
            claTimeAttendMapper.insertScClaTimeAttendAttend(scClaTimeAttend);
        }
    }
}
